package com.tjhk.lock.clh;

import java.util.concurrent.atomic.AtomicReference;

public class MCSLock {

    private static class Node {
           private volatile boolean status = false;
           private volatile Node next = null;
    }
    /**
     * 隐式链表的队尾指针
     */
    private AtomicReference<Node> tail;
    /**
     * 当前节点
     */
    private ThreadLocal<Node> currentNode;

    public MCSLock() {
        this.tail = new AtomicReference<>(null);
        this.currentNode = ThreadLocal.withInitial(Node::new);
    }

    public void lock() {
        Node node = currentNode.get();
        node.status = true;
        // 首次加载是prev获取tail初始值为null
        // 第二次则prev为第一次加锁时NODE
        Node prev = tail.getAndSet(node);
        if (prev != null){
            // 当前节点加入链表
            prev.next = node;
            while (node.status);
        }
    }

    public void unlock(){
        Node node = currentNode.get();
        // 如果当前节点的后继节点为空, 则需要清空队列, 即将队尾指针tail置空
        if( node.next==null ) {
            // 通过CAS的方式安全地将队尾指针tail置空
            if( !tail.compareAndSet(node, null) ) {
                //  如果这个CAS操作失败, 则说明有节点突然入队, 即刚刚执行完lock方法的(1)代码
                //  此时需要等待lock方法的(2)代码完成
                while( node.next==null );
            }
        }

        // 当前节点的后继节点存在
        if( node.next!=null ) {
            // 将当前节点的后继节点的status变量修改为false
            node.next.status = false;
            node.next = null;
        }
        currentNode.remove();
    }
}
